#include <gtest/gtest.h>

#include <algorithm>
#include <functional>
#include <mutex>
#include <future>

// 演示 std::recursive_mutex：同一线程可以多次锁定同一互斥量。
// 这里通过递归调用，确认锁可以重复进入而不会死锁。
TEST(RecursiveMutexTest, ReentrantLocking) {
    std::recursive_mutex rm;
    int depthReached = 0;

    std::function<void(int)> recurse = [&](int depth) {
        std::lock_guard<std::recursive_mutex> lock(rm);
        depthReached = std::max(depthReached, depth);
        if (depth > 0) {
            recurse(depth - 1);
        }
    };

    recurse(3);
    EXPECT_EQ(depthReached, 3);
}

// 演示：当同一线程尚未完全释放递归互斥量时，其他线程无法获得该锁。
// 释放完成后，其他线程才能成功加锁。
TEST(RecursiveMutexTest, OtherThreadsWaitUntilFullyUnlocked) {
    std::recursive_mutex rm;

    std::promise<void> ownerLocked;
    std::promise<void> releaseLocks;

    // 线程 A：连续重入三次，保持持锁状态。
    std::thread owner([&] {
        rm.lock();
        rm.lock();
        rm.lock();
        ownerLocked.set_value();           // 通知已经完成重入;会把 ownerLocked 关联的共享状态标记为“已就绪”，并唤醒所有等待在 ownerLocked.get_future() 的线程。
        releaseLocks.get_future().wait();  // wait() 会一直卡住，直到相应的 promise（也就是主线程持有的 releaseLocks）被设置值或异常。
        rm.unlock();
        rm.unlock();
        rm.unlock();
    });

    ownerLocked.get_future().wait();   // 确保 A 已经持有 3 次锁

    // 线程 B：尝试 try_lock，在 A 未释放前应该失败。
    EXPECT_FALSE(rm.try_lock());

    // 允许线程 A 释放递归锁
    releaseLocks.set_value();
    owner.join();

    // A 已释放，B 现在应能成功加锁。
    EXPECT_TRUE(rm.try_lock());
    rm.unlock();
}